﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class DamageSystem : MonoBehaviour
{
    [Header("VFX")]
    [SerializeField] private GameObject damageVFX;   // 普通伤害特效预制体
    [SerializeField] private GameObject defenceVFX;  // 护盾特效预制体

    [Header("Damage Text")]
    [SerializeField] private GameObject damageTextPrefab; // TMP prefab，单个搞定红白数字
    [SerializeField] private float textFloatDistance = 1f;
    [SerializeField] private float textFloatDuration = 0.6f;

    private Queue<GameObject> damagePool = new Queue<GameObject>();
    private Queue<GameObject> defencePool = new Queue<GameObject>();
    private Queue<GameObject> textPool = new Queue<GameObject>();

    private void OnEnable()
    {
        ActionSystem.AttachPerformer<DealDamageGA>(DealDamagePerformer);
        ActionSystem.AttachPerformer<DealHealGA>(DealHealPerformer);
        ActionSystem.AttachPerformer<DealDefenceGA>(DealDefencePerformer);
        ActionSystem.AttachPerformer<DealWhiteDamageGA>(DealWhiteDamagePerformer);
    }

    private void OnDisable()
    {
        ActionSystem.DetachPerformer<DealDamageGA>();
        ActionSystem.DetachPerformer<DealHealGA>();
        ActionSystem.DetachPerformer<DealDefenceGA>();
        ActionSystem.DetachPerformer<DealWhiteDamageGA>();
    }

    private IEnumerator DealDamagePerformer(DealDamageGA ga) =>
        PerformDamage(ga.Targets, ga.Amount, Color.red);

    private IEnumerator DealWhiteDamagePerformer(DealWhiteDamageGA ga) =>
        PerformDamage(ga.Targets, ga.Amount, Color.white);

    private IEnumerator DealDefencePerformer(DealDefenceGA ga) =>
        PerformDefence(ga.Targets, ga.Amount);
    private IEnumerator DealHealPerformer(DealHealGA ga) =>
        PerformHeal(ga.Targets, ga.Amount);

    private IEnumerator PerformDamage(List<CombatantView> targets, int amount, Color textColor)
    {
        foreach (var target in targets)
        {
            target.Damage(amount);
            Vector3 pos = target.transform.position;

            // 播放普通伤害VFX
            PlayVFX(damageVFX, damagePool, pos);

            // 播放数字特效
            PlayDamageText(amount, pos, textColor);

            yield return new WaitForSeconds(0.15f);

            if (target.CurrentHealth <= 0 && target is EnemyView enemyView)
                ActionSystem.Instance.AddReaction(new KillEnemyGA(enemyView));
        }
    }

    private IEnumerator PerformDefence(List<CombatantView> targets, int amount)
    {
        foreach (var target in targets)
        {
            target.Defence(amount);
            yield return StartCoroutine(PlayDefenceVFX(defenceVFX, defencePool, target.transform.position));
            yield return new WaitForSeconds(0.05f);
        }
    }
    private IEnumerator PerformHeal(List<CombatantView> targets, int amount)
    {
        foreach (var target in targets)
        {
            target.Heal(amount);

            // 播放绿色回血数字
            Vector3 pos = target.transform.position;
            PlayDamageText(amount, pos, Color.green, true); // true 表示加号

            yield return new WaitForSeconds(0.05f);
        }
    }
    // ------------------- VFX -------------------
    private void PlayVFX(GameObject prefab, Queue<GameObject> pool, Vector3 position)
    {
        GameObject obj = GetFromPool(prefab, pool, position);
        StartCoroutine(ReturnToPoolAfter(obj, pool, 0.4f));
    }

    private IEnumerator PlayDefenceVFX(GameObject vfxPrefab, Queue<GameObject> pool, Vector3 position)
    {
        GameObject vfxInstance = GetFromPool(vfxPrefab, pool, position);
        SpriteRenderer sr = vfxInstance.GetComponent<SpriteRenderer>();
        if (sr == null)
        {
            yield return new WaitForSeconds(0.4f);
            ReturnToPool(vfxInstance, pool);
            yield break;
        }

        float halfDuration = 0.2f;
        for (float t = 0; t < halfDuration; t += Time.deltaTime)
        {
            SetAlpha(sr, Mathf.Lerp(0f, 1f, t / halfDuration));
            yield return null;
        }
        SetAlpha(sr, 1f);

        for (float t = 0; t < halfDuration; t += Time.deltaTime)
        {
            SetAlpha(sr, Mathf.Lerp(1f, 0f, t / halfDuration));
            yield return null;
        }
        ReturnToPool(vfxInstance, pool);
    }

    private void SetAlpha(SpriteRenderer sr, float alpha)
    {
        Color c = sr.color;
        c.a = alpha;
        sr.color = c;
    }

    // ------------------- Damage Text -------------------
    private void PlayDamageText(int amount, Vector3 position, Color color, bool isHeal = false)
    {
        GameObject obj = GetFromPool(damageTextPrefab, textPool, position);
        TMP_Text tmp = obj.GetComponent<TMP_Text>();
        tmp.text = (isHeal ? "+" : "-") + amount;
        tmp.color = color;

        StartCoroutine(FloatAndReturn(obj, position));
    }
    private IEnumerator FloatAndReturn(GameObject obj, Vector3 startPos)
    {
        TMP_Text tmp = obj.GetComponent<TMP_Text>();
        if (tmp == null) yield break;

        // 设置渲染队列最前
        tmp.fontMaterial.renderQueue = 4000;

        // 初始颜色
        Color originalColor = tmp.color;
        tmp.color = originalColor;

        // 随机初始偏移
        Vector3 pos = startPos + new Vector3(Random.Range(-0.3f, 0.3f), 0f, 0f);

        // 初速度
        Vector2 velocity = new Vector2(Random.Range(-4f, 4f), Random.Range(5f, 7f));
        float gravity = -10f;
        float totalDuration = 3f;
        float elapsed = 0f;

        obj.transform.localScale = Vector3.one * 0.8f;

        while (elapsed < totalDuration)
        {
            elapsed += Time.deltaTime;
            float t = elapsed / totalDuration;

            // 位置更新
            velocity.y += gravity * Time.deltaTime;
            pos += new Vector3(velocity.x, velocity.y, 0) * Time.deltaTime;
            obj.transform.position = pos;

            // 缩放弹性
            obj.transform.localScale = Vector3.Lerp(Vector3.one * 0.8f, Vector3.one, Mathf.Sin(t * Mathf.PI));

            // 微旋转
            obj.transform.rotation = Quaternion.Euler(0f, 0f, Mathf.Sin(t * Mathf.PI * 6f) * 30f);

            // 渐隐（直接修改 TMP 颜色 alpha）
            Color c = tmp.color;
            c.a = Mathf.Lerp(1f, 0f, t * 2f);
            tmp.color = c;

            yield return null;
        }

        // 回到对象池
        ReturnToPool(obj, textPool);

        // 恢复颜色
        tmp.color = originalColor;
    }

    // ------------------- 对象池 -------------------
    private GameObject GetFromPool(GameObject prefab, Queue<GameObject> pool, Vector3 position)
    {
        GameObject obj;
        if (pool.Count > 0)
        {
            obj = pool.Dequeue();
            obj.transform.position = position;
            obj.SetActive(true);
        }
        else
        {
            obj = Instantiate(prefab, position, Quaternion.identity);
        }
        return obj;
    }

    private void ReturnToPool(GameObject obj, Queue<GameObject> pool)
    {
        obj.SetActive(false);
        pool.Enqueue(obj);
    }

    private IEnumerator ReturnToPoolAfter(GameObject obj, Queue<GameObject> pool, float delay)
    {
        yield return new WaitForSeconds(delay);
        ReturnToPool(obj, pool);
    }
}
